package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.RoleDto;
import com.zzyl.dto.UserDto;
import com.zzyl.entity.Role;
import com.zzyl.entity.RoleResource;
import com.zzyl.entity.User;
import com.zzyl.entity.UserRole;
import com.zzyl.mapper.*;
import com.zzyl.service.RoleService;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.vo.RoleVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Description RoleServiceImpl
 * @Author KangChi Wang
 * @Date 2024-09-04
 */
@Service
public class RoleServiceImpl implements RoleService {
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RoleResourceMapper roleResourceMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 分页查询
     *
     * @param pageNum
     * @param pageSize
     * @param roleDto
     * @return {@link PageResponse }<{@link RoleVo }>
     */
    @Override

    public PageResponse<RoleVo> findRoleVoPage(int pageNum, int pageSize, RoleDto roleDto) {
        //定义key
        String key = "roleCache::" + pageNum + "_" + pageSize + "_" + roleDto.hashCode();
        //先查询redis数据
        String json = redisTemplate.opsForValue().get(key);
        PageResponse<RoleVo> pageResponse = null;
        if (StrUtil.isEmpty(json)) {
            //开启分页查询
            PageHelper.startPage(pageNum, pageSize);
            //查询结果
            Page<Role> page = roleMapper.findRoleVoPage(roleDto);
            //封装结果
            pageResponse = PageResponse.of(page, RoleVo.class);
            //写入缓存
            redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(pageResponse), 30, TimeUnit.MINUTES);
        }else {
            //讲缓存数据转为pageResponse
             pageResponse = JSONUtil.toBean(json, PageResponse.class);

        }


        //返回结果
        return pageResponse;


    }

    /**
     * 添加用户
     *
     * @param roleDto
     */
    @Override
    public Boolean addRole(RoleDto roleDto) {
        //类型转换
        Role role = BeanUtil.toBean(roleDto, Role.class);
        roleMapper.insertSelective(role);
        //清除缓存
        clearCache("roleCache*");

        return true;

    }

    private void clearCache(String key) {
        Set<String> keys = redisTemplate.keys(key);
        redisTemplate.delete(keys);
    }

    /**
     * 根据角色查询选中的资源数据
     *
     * @param roleId
     * @return {@link Set }<{@link String }>
     */
    @Override
    public Set<String> findResource(Long roleId) {
        return roleResourceMapper.selectResourceNoByRoleId(roleId);
    }

    /**
     * 修改角色数据
     *
     * @param roleDto
     * @return {@link Boolean }
     */
    @Override
    public Boolean updateRole(RoleDto roleDto) {
        //1.类型转换
        Role role = BeanUtil.toBean(roleDto, Role.class);


        //2.调用修改角色的mapper
        roleMapper.updateByPrimaryKeySelective(role);
        //3.判断是否修改角色对应的资源数据

        if (roleDto.getCheckedResourceNos() != null) {
            //4.否则不为空，则修改,先删除原有角色资源中间信息，然后再新增角色资源中间信息
            //4.1 删除原有角色资源中间信息
            roleResourceMapper.deleteRoleResourceByRoleId(role.getId());
            if (roleDto.getCheckedResourceNos().length > 0) {
                //4.2 批量新增角色资源中间信息
                //4.2.2 定义一个空list用来存储角色资源实体对象
                List<RoleResource> roleResourceList = new ArrayList<>();
                //4.2.3 遍历封装数据
                String[] checkedResourceNos = roleDto.getCheckedResourceNos();
                List<String> resourceNoList = Arrays.asList(checkedResourceNos);
                resourceNoList.forEach(resourceNo -> {
                    RoleResource roleResource = RoleResource.builder().roleId(role.getId()).resourceNo(resourceNo).dataState(SuperConstant.DATA_STATE_0).build();
                    roleResourceList.add(roleResource);
                });

                //如果集合为空，则结束请求
                if (EmptyUtil.isNullOrEmpty(roleResourceList)) {
                    return true;
                }

                //4.2.1 调用批量新增中间表mapper
                roleResourceMapper.batchInsert(roleResourceList);
            }
        }
        clearCache("roleCache*");
        return true;
    }

    /**
     * 删除角色
     *
     * @param roleId
     */
    @Override
    @Transactional
    public void deleRole(Long roleId) {
        //删除资源
        roleResourceMapper.deleRole(roleId);
        //删除角色
        roleMapper.deleteByPrimaryKey(roleId);
        //删除角色资源的数据
        userRoleMapper.dele(roleId);
        clearCache("roleCache*");
    }

    @Override
    public List<RoleVo> RoleSelect() {
        List<Role> roleList = roleMapper.initRoles();
        return BeanUtil.copyToList(roleList, RoleVo.class);
    }

    @Override
    @Transactional
    public Boolean updateUser(UserDto userDto) {

        //类型转换
        User user = BeanUtil.toBean(userDto, User.class);
        //动态更新
        userMapper.updateByPrimaryKeySelective(user);
        //删除原有的roleVoIds
        roleMapper.deleRoleVoIds(user.getId());
        //插入新的roleVoIds
        ArrayList<UserRole> userRoles = new ArrayList<>();
        userDto.getRoleVoIds().forEach(n -> {
            userRoles.add(UserRole.builder()
                    .userId(user.getId())
                    .roleId(Long.valueOf(n))
                    .dataState(SuperConstant.DATA_STATE_0)
                    .build());
        });
        int flag = userRoleMapper.batchInsert(userRoles);
        if (flag == 0) {
            throw new RuntimeException("保存用户角色信息出错");
        }
        return true;
    }


}
